package service

import (
	"github.com/pkg/errors"
	"log"
	"net"
	"syproxy/protocol"
)

type (
	// Service is body of server
	Service struct {
		Id         string
		Conn       net.Conn
		Send       chan []byte
		Recv       chan *protocol.Pack
		Open       chan string
		CloseMe    chan bool
		CloseOther chan string
	}
)

var authRes = "pass"

func (s *Service) Read() {
	temp := make([]byte, 0)
	for {
		content := make([]byte, 10240)
		// s.Conn.SetReadDeadline(time.Now().Add(time.Duration(30) * time.Second))
		n, err := s.Conn.Read(content)
		if err != nil {
			s.CloseMe <- true
			log.Printf("Read err ! ip: %v, err: %v", s.Conn.RemoteAddr(), err)
			return
		}
		temp = protocol.Unpack(append(temp, content[:n]...), s.Recv)
	}
}

// ReadRaw 读取外界数据
func (s *Service) ReadRaw() {
	for {
		content := make([]byte, 10240)
		n, err := s.Conn.Read(content)
		if err != nil {
			s.CloseMe <- true
			log.Printf("Read err ! id: %v, err: %v", s.Id, err)
			return
		}
		p := new(protocol.Pack)
		p.Id = s.Id
		p.Data = content[:n]
		s.Recv <- p
	}
}

// Write 向 connection 写数据
func (s *Service) Write(content []byte, id []byte) {
	_, err := s.Conn.Write(protocol.Packet(content, id))
	//_, err := s.Conn.Write(content)
	if err != nil {
		s.CloseMe <- true
		log.Printf("Write err! id: %v, err: %v", s.Id, err)
	}
}

// WriteRaw 向 connection 写数据
func (s *Service) WriteRaw(content []byte) {
	_, err := s.Conn.Write(content)
	if err != nil {
		s.CloseMe <- true
		log.Printf("Write err! ip: %v, err: %v", s.Conn.RemoteAddr(), err)
	}
}

// Close
func (s *Service) Close() {
	log.Printf("Peer closed success, id: %v", s.Id)
	s.Conn.Close()
}

// AuthClient is a function that server auth client
func AuthClient(local *Service, authWd string) error {
	passWd := make([]byte, 20)
	n, err := local.Conn.Read(passWd)
	if err != nil {
		return err
	}

	if string(passWd[:n]) != authWd {
		local.Conn.Write([]byte("no"))
		local.Close()
		return errors.New("Client auth error, id: " + local.Id)
	}
	local.Conn.Write([]byte(authRes))
	return nil
}

// AuthToServer is a function that client send auth to server
func AuthToServer(remote *Service, authPw string) error {
	remote.Conn.Write([]byte(authPw))
	content := make([]byte, 20)
	n, err := remote.Conn.Read(content)
	if err != nil {
		return err
	}

	if string(content[:n]) != authRes {
		return errors.New("Auth valid!")
	}

	return nil
}

// NewService create a Service
func NewService() *Service {
	service := new(Service)
	service.Send = make(chan []byte, 2)
	service.Recv = make(chan *protocol.Pack, 5)
	service.CloseMe = make(chan bool, 2)
	service.CloseOther = make(chan string, 2)
	service.Open = make(chan string, 2)
	return service
}
